<?php

/**
 * 安心站长axzz.cn，一个追求技术创造者。让网站、小程序、APP牛起来……
 *
 * cighsen02 365182575
 *
 * Create at: 2025.01.21
 * Update at: 2025.11.24
 */

namespace Twoir\Service;

use Exception;

use function array_filter;
use function array_walk_recursive;
use function basename;
use function class_exists;
use function constant;
use function date;
use function eReturnDomain;
use function ehtmlspecialchars;
use function forward_static_call_array;
use function is_numeric;
use function nl2br;
use function pascal_case;
use function RepFieldtextNbsp;
use function scandir;
use function strtolower;
use function str_contains;

/**
 * 模型调用入口
 */
class BaseInfo
{
    const ALLOW_METHODS = [
        'getCount',
        'getCheckCount',
        'getDocCount',
        'getOne',
        'getCheckOne',
        'getDocOne',
        'getCheckList',
        'getDocList',
        'getList',
        'insert',
        'insertCheck',
        'insertDoc',
        'update',
        'updateCheck',
        'updateDoc',
        'delete',
        'deleteCheck',
        'deleteDoc',
        'enableLowPriority',
        'disableLowPriority'
    ];
    // 当前操作的表
    protected ?string $tablename = null;

    protected ?int $tid = null;

    protected ?int $mid = null;

    // 父栏目id
    protected ?int $bclassid = null;

    // 当前栏目id
    protected ?int $classid = null;

    /**
     * 栏目id
     *
     * @param int|null $classid
     */
    public function __construct($classid = null)
    {
        $this->initialize($classid);
    }

    /**
     * 重设置classid
     *
     * @param int $classid
     * @return static
     */
    public function setClassId(int $classid): static
    {
        // 如果与旧相同，跳过
        if ($classid && $classid !== $this->classid) {
            // 重置
            $this->tablename 	= null;
            $this->tid			= null;
            $this->mid			= null;
            $this->bclassid 	= null;

            $this->initialize($classid);
        }

        return $this;
    }

    /**
     * 重设置tablename
     *
     * @param string $tablename
     * @return static
     */
    public function setTableName(string $tablename): static
    {
        // 如果与旧相同，跳过
        if ($tablename && strtolower($tablename) !== strtolower($this->tablename)) {
            // 重置
            $this->tablename 	= null;
            $this->tid			= null;
            $this->mid			= null;
            $this->bclassid 	= null;

            $this->initialize($tablename);
        }

        return $this;
    }

    /**
     * 返回查询条件
     *
     * @param int $classid
     * @return array
     */
    public function getWhere(int $classid): array
    {
        global $class_r;

        // 顶级栏目
        if(0 === $this->bclassid) return [];

        // 非终级栏目
        if($classid && isset($class_r[$classid]['islast'], $class_r[$classid]['islist']) && 0 === $class_r[$classid]['islast'] && 1 === $class_r[$classid]['islist']) {

            $str = $class_r[$classid]['sonclass'] ? trim($class_r[$classid]['sonclass'], '|') : $classid;

            return str_contains($str, '|') ? ['classid in' => explode('|', $str)] : ['classid' => $classid];
        }

        // 终级栏目
        return ['classid' => $classid];
    }

    /**
     * 调用数据库类名
     * 
     * @return string
     * 
     * @throws Exception
     */
    private function className(): string
    {
        if (empty($this->classid)) throw new Exception('参数错误', 9200);

        if (empty($this->tablename)) throw new Exception('模型未找，请确定生成了', 9200);

        if (!class_exists('Twoir\System\Model\\' . $this->tablename)) throw new Exception('请先建立模型，再操作', 9200);

        return 'Twoir\System\Model\\' . $this->tablename;
    }

    /**
     * 获得模型名称
     *
     * @return string
     */
    public function modelName(): string
    {
        return constant($this->className() . '::MODEL');
    }

    /**
     * 获取字段
     * 
     * @param string $type
     * @return array
     */
    protected function field(?string $type = null): array
    {
        if ($type && !in_array($type, ['index', 'pri', 'sec'])) throw new Exception('type类型错误', 9200);

        $fields = constant($this->className() . '::FIELD');

        if (null === $type) {

            $fields = array_merge($fields['pri'], $fields['sec']);

            $fields = array_unique($fields);

            return array_values($fields);
        }

        return $fields[$type];
    }

    /**
     * 格式化数据
     *
     * @param array $data
     * @return array
     */
    protected function format(array $data): array
    {
        global $emod_r;

        if (empty($data)) return [];

        array_walk_recursive($data, function(&$value, $key) use($emod_r) {
            // 时间
            if (in_array($key, ['newstime', 'truetime', 'lastdotime'])) {
                // Y-m-d H:i:s
                $value = date('Y-m-d', $value);
            }
            // 拼上域名
            elseif ($key === 'titleurl') {
                $value = eReturnDomain() . $value;
            }
            else{
                // 转义
                if (isset($emod_r[$this->mid]['editorf']) && !str_contains($emod_r[$this->mid]['editorf'], ',' . $key . ',')) {
                    // 加br
                    if(isset($emod_r[$this->mid]['tobrf']) && str_contains($emod_r[$this->mid]['tobrf'], ',' . $key . ',')){

                        $value = nl2br($value);
                    }
                    // 去除html
                    if(isset($emod_r[$this->mid]['dohtmlf']) && !str_contains($emod_r[$this->mid]['dohtmlf'], ',' . $key . ',')){

                        $value = RepFieldtextNbsp(ehtmlspecialchars($value));
                    }
                }
            }
        });

        return $data;
    }

    /**
     * 初始化
     *
     * @param string|int $classid
     * @return void
     *
     * @throws Exception
     */
    protected function initialize($classid = null): void
    {
        global $class_r, $etable_r;

        if ($classid && !is_numeric($classid)) {

            $this->tablename 	= $this->methodName($classid);
            $this->mid 			= $this->tablename ? ($etable_r[$this->tablename]['mid'] ?? null) : null;
        }
        elseif ($classid && isset($class_r[$classid]['tbname'])) {

            if (empty($class_r[$classid]['tbname'])) throw new Exception("参数错误!", 9200);

            $this->tablename    = $this->methodName($class_r[$classid]['tbname']);
            $this->tid			= $class_r[$classid]['tid'] ?? null;
            $this->mid			= $class_r[$classid]['modid'] ?? null;;
            $this->bclassid     = $class_r[$classid]['bclassid'] ?? null;
            $this->classid      = $classid;
        }
    }

    /**
     * 返回简短方法名称
     *
     * @param string $method 调用方法
     * @return string|null
     */
    protected function methodName(string $method): ?string
    {
        $method = pascal_case($method);

        foreach (array_filter(scandir(dirname(__DIR__) . DIRECTORY_SEPARATOR . 'System' . DIRECTORY_SEPARATOR . 'Model'), fn($item) => '.' !== $item && '..' !== $item) as $item) {

            $item = basename($item, '.php');
            if (strtolower($method) === strtolower($item)) return $item;
        }

        return null;
    }

    /**
     * 未指定调用
     *
     * @param string $name
     * @param array $parameters
     * @return object|array|string|int
     * 
     * @throws Exception
     */
    public function __call(string $name, array $parameters)
    {
        if (!in_array($name, static::ALLOW_METHODS, true)) throw new Exception('参数错误', 9200);

        return forward_static_call_array([$this->className(), $name], $parameters);
    }
}
